package app

import (
	"strings"
	"sync"

	"github.com/gin-gonic/gin"
)

var (
	registerLock  sync.Mutex //注册锁
	beforeAopInfo = make(map[string][]func(ctx *gin.Context, params ...interface{}) (bool, string, interface{}))
	afterAopInfo  = make(map[string][]func(ctx *gin.Context, params ...interface{}) (bool, string, interface{}))
	aroundAopInfo = make(map[string][]func(ctx *gin.Context, params ...interface{}) (bool, string, interface{}))
)

/**
 * 注册Aop-函数执行前调用函数
 * @param funcName 被监听函数
 * @param doFunc 被调用函数
 * @return
 */
func RegisterBefore(funcName string, doFunc func(ctx *gin.Context, params ...interface{}) (bool, string, interface{})) {
	funcName = strings.TrimSpace(funcName)
	if funcName == "" {
		return
	}

	registerLock.Lock()
	defer registerLock.Unlock()

	funcArray, ok := beforeAopInfo[funcName]
	if ok {
		funcArray = append(funcArray, doFunc)
		beforeAopInfo[funcName] = funcArray
		return
	}

	funcArray = []func(ctx *gin.Context, params ...interface{}) (bool, string, interface{}){doFunc}
	beforeAopInfo[funcName] = funcArray
}

/**
 * 注册Aop-函数执行后调用函数
 * @param funcName 被监听函数
 * @param doFunc 被调用函数
 * @return
 */
func RegisterAfter(funcName string, doFunc func(ctx *gin.Context, params ...interface{}) (bool, string, interface{})) {
	funcName = strings.TrimSpace(funcName)
	if funcName == "" {
		return
	}

	registerLock.Lock()
	defer registerLock.Unlock()

	funcArray, ok := afterAopInfo[funcName]
	if ok {
		funcArray = append(funcArray, doFunc)
		afterAopInfo[funcName] = funcArray
		return
	}

	funcArray = []func(ctx *gin.Context, params ...interface{}) (bool, string, interface{}){doFunc}
	afterAopInfo[funcName] = funcArray
}

/**
 * 注册Aop-函数执行中调用函数
 * @param funcName 被监听函数 xxservice.xx
 * @param doFunc 被调用函数
 * @return
 */
func RegisterAround(funcName string, doFunc func(ctx *gin.Context, params ...interface{}) (bool, string, interface{})) {
	funcName = strings.TrimSpace(funcName)
	if funcName == "" {
		return
	}

	registerLock.Lock()
	defer registerLock.Unlock()

	funcArray, ok := aroundAopInfo[funcName]
	if ok {
		funcArray = append(funcArray, doFunc)
		aroundAopInfo[funcName] = funcArray
		return
	}

	funcArray = []func(ctx *gin.Context, params ...interface{}) (bool, string, interface{}){doFunc}
	aroundAopInfo[funcName] = funcArray
}

/**
 * 调用Aop-函数执行前调用函数
 * @param funcName 被监听函数 xxservice.xx
 * @param doFunc 被调用函数
 * @return
 */
func CallBeforeFunc(funcName string, ctx *gin.Context, params ...interface{}) (bool, string, interface{}) {
	return callFunc(beforeAopInfo, funcName, ctx, params)
}

/**
 * 调用Aop-函数执行后调用函数
 * @param funcName 被监听函数 xxservice.xx
 * @param doFunc 被调用函数
 * @return
 */
func CallAfterFunc(funcName string, ctx *gin.Context, params ...interface{}) (bool, string, interface{}) {
	return callFunc(afterAopInfo, funcName, ctx, params)
}

/**
 * 调用Aop-函数执行中调用函数
 * @param funcName 被监听函数 xxservice.xx
 * @param doFunc 被调用函数
 * @return
 */
func CallAroundFunc(funcName string, ctx *gin.Context, params ...interface{}) (bool, string, interface{}) {
	return callFunc(aroundAopInfo, funcName, ctx, params)
}

/**
 * 调用Aop-函数执行中调用函数
 * @param aopInfo aop信息
 * @param funcName 被监听函数 xxservice.xx
 * @param doFunc 被调用函数
 * @return
 */
func callFunc(aopInfo map[string][]func(ctx *gin.Context, params ...interface{}) (bool, string, interface{}),
	funcName string, ctx *gin.Context, params []interface{}) (bool, string, interface{}) {
	if funcName == "" {
		return true, "函数名为空,不处理", 1000
	}

	funcArray, ok := aopInfo[funcName]
	if !ok {
		return true, "没有函数,不处理", 1001
	}

	if len(funcArray) < 1 {
		return true, "没有调用函数,结束AOP处理", 1002
	}

	for _, fun := range funcArray {
		bl, msg, res := fun(ctx, params...)
		if !bl {
			return bl, msg, res
		}
	}

	return true, "调用函数没有错误,结束AOP处理", 1003
}
